﻿using System;
using System.Linq;
using System.Reflection;
using System.Collections;
using System.Configuration.Install;

namespace King.Box.Install.Impl
{
    public abstract class ServiceHost : IServiceHost
    {
        protected ServiceHost() { }

        protected virtual void Initialize() { }

        protected virtual void OnInstall()
        {
            try
            {
                string location = Assembly.GetEntryAssembly().Location;
                string[] commandLine = new string[0];
                AssemblyInstaller installerAssembly = new AssemblyInstaller(location, commandLine);
                TransactedInstaller installer = new TransactedInstaller();
                installer.Installers.Add(installerAssembly);
                installer.Install(new Hashtable());
            }
            catch (Exception exception)
            {
                Console.WriteLine($"install service failed: {exception}");
            }
        }

        protected virtual void OnUninstall()
        {
            try
            {
                string location = Assembly.GetEntryAssembly().Location;
                string[] commandLine = new string[0];
                AssemblyInstaller installer = new AssemblyInstaller(location, commandLine);
                TransactedInstaller installerNow = new TransactedInstaller();
                installerNow.Installers.Add(installer);
                installerNow.Uninstall(null);
            }
            catch (Exception exception)
            {
                Console.WriteLine($"uninstall service failed: {exception}");
            }
        }

        public void Run()
        {
            this.Run(new string[0]);
        }

        public void Run(string[] args)
        {
            if (args == null)
                throw new ArgumentNullException("args");

            if (args.Length == 0)
            {
                this.RunAsService(new string[0]);
                return;
            }

            var cmd = args[0].Trim().ToLower();
            //处理后续命令行
            string[] continueCmd = args.Skip<string>(1).ToArray<string>();
            switch (cmd)
            {
                case "-i":
                case "/i":
                    this.OnInstall();
                    break;
                case "-u":
                case "/u":
                    this.OnUninstall();
                    break;
                case "-d":
                case "/d":
                    this.RunAsConsole(continueCmd);
                    break;
                case "-s":
                case "/s":
                    this.RunAsService(continueCmd);
                    break;
                default:
                    Console.Write("unknown method");
                    break;
            }
        }

        protected abstract void RunAsConsole(string[] args);
        protected abstract void RunAsService(string[] args);
    }
}
